/* PLAYGROUND PER PATRIZIO */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.h"
#include "graph.h"
#include "los.h" //per macro flags stato uscita mossa
#include "solution.h"
#include "graphbmp-tools.h"
#include "tabooState.h"
#include "configparser.h" // per configurazione da file
#include "ALGConfiguration.h" // per configurazione da file
#define DRAW

/**
 * @param argn il numero di parametri da inserire nell'algoritmo. Inserire, <b>secondo questo ordine </b>, i parametri:
 * 	@li un file in cui e' contenuto il grafo
 * 	@li il numero di camion da utilizzare
 * @param args i vari input da inserire nel nostor algoritmo. Inserire per il momento solo il file contenente il grafo
 * @return 0 se tutto va bene; 1 se c'e' qualche problema di non natura non meglio specificata.
 */
int main(int argn, const char** args){
	// ********************** VARIABILI DEL PROGRAMMA ************************
	int __N__;
	int __K__ = 0;
	TabooExpire itSTMadd = 0, itSTMswap = 0, itSTMremove = 0, itSTM;
	Pgraph graph;
	Psolution solution;
	PtabooState tabooState;
	FILE* f_config;
	FILE* f_graph;
	FILE* f_bitmap;
	FILE* f_octave;

	if (argn==5){
		f_config = fopen(args[1], "r");
		itSTMadd = (TabooExpire)atoi(args[2]);
		itSTMswap = (TabooExpire)atoi(args[3]);
		itSTMremove = (TabooExpire)atoi(args[4]);
	}else{
		printf("numero di parametri passati errati.\n");
		return EXIT_FAILURE;
	}

	//***************** LETTURA DA FILE ***************
	PalgConfiguration pALGconfig = parseConfigurationFile(f_config);
	__K__ = pALGconfig->vehicleNumber;
	f_bitmap = fopen(pALGconfig->constructiveDrawingPath, "w");
	f_graph = fopen(pALGconfig->graphPath, "r");

	itSTM = itSTMadd + itSTMswap + itSTMremove;
	pLOSConfiguration pLOSconfig = initLOSConfiguration(pALGconfig);

	//***************** COSTRUZIONE STRUTTURE DATI BASE ***************
	graph = parseGraph(f_graph, &__N__);
	graphCorrector(graph);
	dijkstraFiller(graph);              //setEdgeGraphByID(graph, 8, 10, 10, 1, 99);
	printWholeMatrix(stdout, graph);
	printf("T = %d, Q = %d\n", graph->T, graph->Q);

	initSmartWeights(graph);
	solution = initSolution(&__K__, &__N__);
	tabooState = initTabooState(&__N__, &__K__, 0);
	printf("\n~~~~~~~~~~~~inizializzazione finita~~~~~~~~~~~\n");
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	buildSimpleConstructive(graph,solution,tabooState);
	printf("\n~~~~~~~~~~~~iterazione 0: costruttiva~~~~~~~~~~~\n");
	printVehicles(stdout, solution);
	printTabooStateAsSet(stdout, tabooState, 0); // perchè vista DOPO il solveXneighbourhood!!
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	TabooExpire i;
	int k, exitStatus;

	// ~~~~~~ init matlab/octave plot script and save constructive ~~~~~~~~~~~~~~~~~~~~~~
	f_octave = fopen("../matlab-interface/patTest.m", "w");

	fprintf(f_octave, "clear, clc, close all; X = zeros(%lu,3,%d);\n", itSTM+1, __K__);

	for(k=0; k<__K__; k++) {
		fprintf(f_octave, "X(1,1,%d) = %d; ",  k+1, graph->T - getVehicleStateInSolution(solution,k)->tau);
		fprintf(f_octave, "X(1,2,%d) = %d; ",  k+1, graph->Q - getVehicleStateInSolution(solution,k)->theta);
		fprintf(f_octave, "X(1,3,%d) = %d;\n", k+1,            getVehicleStateInSolution(solution,k)->jk);
	}
	fprintf(f_octave, "\n");
	// ~~~~~~ run and save #itSTMadd add iterations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for(i=1; i<=itSTMadd; i++) {
		printf("\n~~~~~~~~~~~~iterazione %lu: ADD~~~~~~~~~~~~\n", i);

		for(k=0; k<__K__; k++) {

			if(k)
				printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
			PvehicleState pvs = getVehicleStateInSolution(solution,k);
			PtabooList ptl = getTabooListInTabooState(tabooState, k);

			exitStatus = solveAddNeighbourhood(graph, pvs, solution->gMatrix, k, ptl, i, pLOSconfig, false);
			if ( exitStatus==MOVE_STATUS_IMPROVE )
				printf("\nadd effettuato con miglioramento.\n");
			else if ( exitStatus==MOVE_STATUS_WORSEN )
				printf("\nadd effettuato con peggioramento.\n");
			else
				printf("\nadd non effettuato, risorse finite.\n");

			printVehicleState(stdout, pvs, k);
			printRemainingResources(stdout, graph, pvs->tau, pvs->theta);
			printVehicleGathering(stdout, pvs->pvp, solution->gMatrix, k);
			printTabooListAsSet(stdout, ptl, i, k);

			fprintf(f_octave, "X(%lu,1,%d) = %d; ",  i+1, k+1, graph->T - pvs->tau);
			fprintf(f_octave, "X(%lu,2,%d) = %d; ",  i+1, k+1, graph->Q - pvs->theta);
			fprintf(f_octave, "X(%lu,3,%d) = %d;\n", i+1, k+1,            pvs->jk);

		}
		fprintf(f_octave,"\n");
	}

	// ~~~~~~ draw solution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#ifdef DRAW
		drawSolutionFromScratchDefaults( "file_sol.bmp", solution, 0);
		char buffer[100];
		sprintf(buffer,"../pictures/swap%lu.bmp",i-1);
				drawSolutionFromScratchDefaults(buffer, solution,0);
	#endif

	// ~~~~~~ run and save #itSTMswap swap iterations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for(i=itSTMadd+1; i<=itSTMadd+itSTMswap; i++) {
		printf("\n~~~~~~~~~~~~iterazione %lu: SWAP~~~~~~~~~~~~\n", i);
		for(k=0; k<__K__; k++) {

			if(k)
				printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
			PvehicleState pvs = getVehicleStateInSolution(solution,k);
			PtabooList ptl = getTabooListInTabooState(tabooState, k);

			exitStatus = solveSwapNeighbourhood(graph, pvs, solution->gMatrix, k, ptl, i, pLOSconfig, false);
			if ( exitStatus==MOVE_STATUS_IMPROVE )
				printf("\nswap effettuato con miglioramento.\n");
			else if ( exitStatus==MOVE_STATUS_WORSEN )
				printf("\nswap effettuato con peggioramento.\n");
			else
				printf("\nswap non effettuato, risorse finite.\n");


			printVehicleState(stdout, pvs, k);
			printRemainingResources(stdout, graph, pvs->tau, pvs->theta);
			printVehicleGathering(stdout, pvs->pvp, solution->gMatrix, k);
			printTabooListAsSet(stdout, ptl, i, k);

			fprintf(f_octave, "X(%lu,1,%d) = %d; ",  i+1, k+1, graph->T - pvs->tau);
			fprintf(f_octave, "X(%lu,2,%d) = %d; ",  i+1, k+1, graph->Q - pvs->theta);
			fprintf(f_octave, "X(%lu,3,%d) = %d;\n", i+1, k+1,            pvs->jk);
		}
		#ifdef DRAW
			sprintf(buffer,"../pictures/swap%lu.bmp",i);
			drawSolutionFromScratchDefaults(buffer,solution,0);
		#endif
		fprintf(f_octave,"\n");
	}

	// ~~~~~~ run and save #itSTMremove remove iterations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for(i=itSTMadd+itSTMswap+1; i<=itSTM; i++) {
		printf("\n~~~~~~~~~~~~~~~~~~~~~~~~iterazione %lu: REMOVE~~~~~~~~~~~~~~~~~~~~~~~~\n", i);
		for(k=0; k<__K__; k++) {

			if(k)
				printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
			PvehicleState pvs = getVehicleStateInSolution(solution,k);
			PtabooList ptl = getTabooListInTabooState(tabooState, k);

			exitStatus = solveRemoveNeighbourhood(graph, pvs, solution->gMatrix, k, ptl, i, pLOSconfig, false);
			if ( exitStatus==MOVE_STATUS_IMPROVE )
				printf("\nremove effettuato con miglioramento.\n");
			else if ( exitStatus==MOVE_STATUS_WORSEN )
				printf("\nremove effettuato con peggioramento.\n");
			else if ( exitStatus==MOVE_STATUS_UNCHANGED )
				printf("\nremove effettuato, profitto invariato.\n");
			else
				printf("\nremove non effettuato, risorse finite.\n");

			printVehicleState(stdout, pvs, k);
			printRemainingResources(stdout, graph, pvs->tau, pvs->theta);
			printVehicleGathering(stdout, pvs->pvp, solution->gMatrix, k);
			printTabooListAsSet(stdout, ptl, i, k);

			fprintf(f_octave, "X(%lu,1,%d) = %d; ",  i+1, k+1, graph->T - pvs->tau);
			fprintf(f_octave, "X(%lu,2,%d) = %d; ",  i+1, k+1, graph->Q - pvs->theta);
			fprintf(f_octave, "X(%lu,3,%d) = %d;\n", i+1, k+1,            pvs->jk);
		}
		#ifdef DRAW
			sprintf(buffer,"../pictures/remove%lu.bmp",i);
			drawSolutionFromScratchDefaults(buffer,solution,0);
		#endif
		fprintf(f_octave,"\n");
	}

	// ~~~~~~ finalize scripts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for(k=0; k<__K__; k++) {

		fprintf(f_octave, "\nfigure('name', 'Vehicle%d')\n",k+1);
		fprintf(f_octave, "plot(0:%lu, X(:,1,%d),'r'), hold on\n",itSTM, k+1);
		fprintf(f_octave, "plot(0:%lu, X(:,2,%d),'g')\n",itSTM, k+1);
		fprintf(f_octave, "plot(0:%lu, X(:,3,%d),'b')\n",itSTM, k+1);
		fprintf(f_octave, "yL = get(gca,'YLim');\n");
		fprintf(f_octave, "line([1 1],yL,'Color','y')\n");
		fprintf(f_octave, "line([%lu %lu],yL,'Color','k')\n", itSTMadd, itSTMadd);
		fprintf(f_octave, "line([%lu %lu],yL,'Color','c')\n", itSTMadd+itSTMswap, itSTMadd+itSTMswap);
		fprintf(f_octave, "legend('T-\\tau','Q-\\theta','J_k', 'Add', 'Swap', 'Remove'), axis tight\n");
	}
	fclose(f_octave);

	// ~~~~~~ print final program state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for(k=0; k<__K__; k++) {

		if(k)
			printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
		else
			printf("\n\n\n~~~~FINAL PROGRAM STATE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
		PvehicleState pvs = getVehicleStateInSolution(solution,k);
		PtabooList ptl = getTabooListInTabooState(tabooState, k);

		printVehicleState(stdout, pvs, k);
		printRemainingResources(stdout, graph, pvs->tau, pvs->theta);
		printVehicleGathering(stdout, pvs->pvp, solution->gMatrix, k);
		printTabooListAsSet(stdout, ptl, i, k);
	}
	printf("FINE.\n");
}
